/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.seguradora.model.repository.impl;

import br.com.seguradora.exception.PersistenciaException;
import br.com.seguradora.model.Marca;
import br.com.seguradora.model.Modelo;
import br.com.seguradora.model.repository.TodosModelos;
import br.com.seguradora.persistence.GerenciadorDeConexao;
import br.com.seguradora.view.DisplayFilter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Diego
 */
public class TodosModelosImpl implements TodosModelos {

    private Connection conn;
    private PreparedStatement pr;
    private ResultSet rs;

    @Override
    public boolean inserir(Modelo modelo) throws PersistenciaException {
        if (modelo == null) {
            throw new PersistenciaException("Não foi informado o modelo a cadastrar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("INSERT INTO MODELO(ID, BLOQUEADO, NOME, ID_MARCA, SHADOW) VALUES(NULL, FALSE, ?, ?, FALSE);",
                    Statement.RETURN_GENERATED_KEYS);
            pr.setString(1, modelo.getNome());
            pr.setLong(2, modelo.getMarca().getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
                rs = pr.getGeneratedKeys();
                rs.first();
                long id = rs.getLong(1);
                modelo.setId(id);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar o modelo.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return sucesso;
    }

    @Override
    public boolean atualizar(Modelo modelo) throws PersistenciaException {
        if (modelo == null) {
            throw new PersistenciaException("Não foi informado o modelo a atualizar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE MODELO SET BLOQUEADO=?, NOME=?, ID_MARCA=? WHERE ID=?;");
            pr.setBoolean(1, modelo.isBloqueado());
            pr.setString(2, modelo.getNome());
            pr.setLong(3, modelo.getMarca().getId());
            pr.setLong(4, modelo.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar o modelo.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public boolean excluir(Modelo modelo) throws PersistenciaException {
        if (modelo == null) {
            throw new PersistenciaException("Não foi informado o modelo a excluir.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE MODELO SET SHADOW=TRUE WHERE ID=?;");
            pr.setLong(1, modelo.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível excluir o modelo.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public List<Modelo> listarTodos(int... limits) throws PersistenciaException {
        List<Modelo> lista = new ArrayList<Modelo>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT M.ID, M.BLOQUEADO, M.NOME, M.ID_MARCA, MA.NOME AS NOME_MARCA FROM MODELO M INNER JOIN MARCA MA ON M.ID_MARCA = MA.ID WHERE M.SHADOW=FALSE ORDER BY M.ID DESC LIMIT ?, ?;");
            pr.setInt(1, limits[0]);
            pr.setInt(2, limits[1]);
            rs = pr.executeQuery();
            while (rs.next()) {
                Modelo modelo = this.criarModelo(rs);
                lista.add(modelo);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os modelos.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Modelo> listarPelaMarca(Marca marca, String nome, DisplayFilter displayFilter) throws PersistenciaException {
        List<Modelo> lista = new ArrayList<Modelo>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (displayFilter != DisplayFilter.TODOS) {
                pr = conn.prepareStatement("SELECT M.ID, M.BLOQUEADO, M.NOME, M.ID_MARCA, MA.NOME AS NOME_MARCA FROM MODELO M INNER JOIN MARCA MA ON M.ID_MARCA = MA.ID WHERE M.SHADOW=FALSE AND M.ID_MARCA=? AND M.NOME LIKE ? AND M.BLOQUEADO=? ORDER BY M.NOME");
                pr.setBoolean(3, displayFilter.getValue());
            } else {
                pr = conn.prepareStatement("SELECT M.ID, M.BLOQUEADO, M.NOME, M.ID_MARCA, MA.NOME AS NOME_MARCA FROM MODELO M INNER JOIN MARCA MA ON M.ID_MARCA = MA.ID WHERE M.SHADOW=FALSE AND M.ID_MARCA=? AND M.NOME LIKE ? ORDER BY M.NOME");
            }
            pr.setLong(1, marca.getId());
            pr.setString(2, "%" + nome + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Modelo modelo = this.criarModelo(rs);
                lista.add(modelo);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os modelos por nome.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private Modelo criarModelo(ResultSet rs) throws PersistenciaException {
        Modelo modelo = null;
        try {
            modelo = new Modelo(rs.getLong("ID"));
            modelo.setBloqueado(rs.getBoolean("BLOQUEADO"));
            modelo.setNome(rs.getString("NOME"));

            Marca marca = new Marca(rs.getLong("ID_MARCA"), rs.getString("NOME_MARCA"));
            modelo.setMarca(marca);
        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do modelo.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return modelo;
    }

    @Override
    public List<Modelo> listarPeloNome(String nome, DisplayFilter displayFilter) throws PersistenciaException {
        List<Modelo> lista = new ArrayList<Modelo>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            if (displayFilter != DisplayFilter.TODOS) {
                pr = conn.prepareStatement("SELECT M.ID, M.BLOQUEADO, M.NOME, M.ID_MARCA, MA.NOME AS NOME_MARCA FROM MODELO M INNER JOIN MARCA MA ON M.ID_MARCA = MA.ID WHERE M.SHADOW=FALSE AND M.NOME LIKE ? AND M.BLOQUEADO=? ORDER BY M.NOME");
                pr.setBoolean(2, displayFilter.getValue());
            } else {
                pr = conn.prepareStatement("SELECT M.ID, M.BLOQUEADO, M.NOME, M.ID_MARCA, MA.NOME AS NOME_MARCA FROM MODELO M INNER JOIN MARCA MA ON M.ID_MARCA = MA.ID WHERE M.SHADOW=FALSE AND M.NOME LIKE ? ORDER BY M.NOME");
            }
            pr.setString(1, "%" + nome + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Modelo modelo = this.criarModelo(rs);
                lista.add(modelo);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os modelos por nome.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }
}
